package com.kaibes.core.base.util;

import java.nio.charset.Charset;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.kaibes.core.base.BaseConfig;
import com.kaibes.core.base.builder.SeparatorBuilder;

public class StringUtils {

    public static int length(String str) {
        return str == null ? 0 : str.length();
    }
    
    public static boolean isBlankOrNotStartsWith(String source, String start) {
        return isBlank(source) || !source.startsWith(start);
    }
    public static boolean isBlankOrStartsWith(String source, String start) {
        return isBlank(source) || source.startsWith(start);
    }
    public static boolean isBlankOrMatchers(String source, String start) {
        if (isBlank(source)) {
            return true;
        }
        if (source.endsWith("/**")) {
            source = source.substring(0, source.length()-3);
            return start.startsWith(source);
        }
        return source.equals(start);
    }
    
    public static boolean equals(String source, String...equals) {
        for (String equal : equals) {
            if (source.equals(equal)) {
                return true;
            }
        }
        return false;
    }
    
    public static boolean endsWith(String source, String...ends) {
        for (String end : ends) {
            if (source.endsWith(end)) {
                return true;
            }
        }
        return false;
    }
    
    public static boolean notEndsWith(String source, String...ends) {
        for (String end : ends) {
            if (source.endsWith(end)) {
                return false;
            }
        }
        return true;
    }
    
    public static boolean startsWith(String source, String...starts) {
        for (String start : starts) {
            if (source.startsWith(start)) {
                return true;
            }
        }
        return false;
    }

    public static boolean isEmpty(String str) {
        return str == null || str.isEmpty();
    }

    public static boolean isNotEmpty(String str) {
        return str != null && !str.isEmpty();
    }

    public static boolean isBlank(String str) {
        return str == null || str.trim().isEmpty();
    }

    public static boolean isNotBlank(String str) {
        return str != null && !str.trim().isEmpty();
    }

    public static boolean isBlankOr(String str, String or) {
        return str == null || str.trim().isEmpty() || str.trim().equals(or);
    }

    public static boolean startWith(List<String> list, String start) {
        if (list != null) {
            for (int i = 0; i < list.size(); i++) {
                boolean flag = list.get(i).startsWith(start);
                if (flag) {
                    return true;
                }
            }
        }
        return false;
    }

    public static boolean startWith(String str, List<String> list) {
        for (int i = 0; i < list.size(); i++) {
            boolean flag = str.startsWith(list.get(i));
            if (flag) {
                return true;
            }
        }
        return false;
    }

    public static boolean startWith(String str, String start) {
        return str != null && str.startsWith(start);
    }

    public static boolean endWith(String str, String end) {
        return str != null && str.endsWith(end);
    }

    public static String format(String format, Object... args) {
        return String.format(format, args);
    }

    private static Pattern humpPattern = Pattern.compile("[A-Z]");

    public static String humpToLine(String str) {
        Matcher matcher = humpPattern.matcher(str);
        StringBuffer sb = new StringBuffer();
        while (matcher.find()) {
            matcher.appendReplacement(sb, "_" + matcher.group(0).toLowerCase());
        }
        matcher.appendTail(sb);
        return sb.toString();
    }

    public static boolean isHump(String str) {
        byte[] bs = str.getBytes();
        for (byte b : bs) {
            if (b >= 65 && b <= 90) {
                return true;
            }
        }
        return false;
    }

    private static char[] strs = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
            'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B',
            'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
            'X', 'Y', 'Z', '~', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', '-', '=' };
    private static char[] nums = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };

    public static String random(int length) {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < length; i++) {
            int index = (int) (Math.random() * strs.length);
            sb.append(strs[index]);
        }
        return sb.toString();
    }

    public static String randomNum(int length) {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < length; i++) {
            int index = (int) (Math.random() * nums.length);
            sb.append(nums[index]);
        }
        return sb.toString();
    }

    /**
     * 将byte转换为16进制字符串
     * 
     * @param src
     * @return
     */
    public static String byteToHexString(byte[] src) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < src.length; i++) {
            int v = src[i] & 0xff;
            String hv = Integer.toHexString(v);
            if (hv.length() < 2) {
                sb.append("0");
            }
            sb.append(hv);
        }
        return sb.toString();
    }

    /**
     * 将16进制字符串装换为byte数组
     * 
     * @param hexString
     * @return
     */
    public static byte[] hexStringToBytes(String hexString) {
        hexString = hexString.toUpperCase();
        int length = hexString.length() / 2;
        char[] hexChars = hexString.toCharArray();
        byte[] b = new byte[length];
        for (int i = 0; i < length; i++) {
            int pos = i * 2;
            b[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));
        }
        return b;
    }

    public static String stringToHexString(String source) {
        return byteToHexString(getBytes(source));
    }

    public static String hexStringToString(String source) {
        return getString(hexStringToBytes(source));
    }

    private static byte charToByte(char c) {
        return (byte) "0123456789ABCDEF".indexOf(c);
    }

    public static byte[] getBytes(String str) {
        return str.getBytes(BaseConfig.charset);
    }

    public static String getString(byte[] bs, Charset charset) {
        return new String(bs, charset);
    }
    
    public static String getString(byte[] bs) {
        return new String(bs, BaseConfig.charset);
    }

    public static SeparatorBuilder separatorBuilder(String separator) {
        return new SeparatorBuilder(separator);
    }

    // =========
    private final static String _caseString(String str) {
        if (str == null || str.trim().isEmpty()) {
            return str;
        }
        char[] cs = str.toCharArray();
        StringBuilder allSb = new StringBuilder();
        StringBuilder sb = new StringBuilder();
        sb.append(cs[0]);
        for (int i = 1; i < cs.length; i++) {
            if (cs[i] > 64 && cs[i] < 91) {
                allSb.append(sb).append("_");
                sb.setLength(0);
            }
            sb.append(cs[i]);
        }
        if (sb.length() > 0) {
            allSb.append(sb);
        }
        return allSb.toString();
    }

    public final static String upper_caseString(String str) {
        return upperCaseString(_caseString(str));
    }

    public final static String lower_caseString(String str) {
        return lowerCaseString(_caseString(str));
    }

    public final static String upperCaseString(String str) {
        char[] cs = str.toCharArray();
        for (int i = 0; i < cs.length; i++) {
            cs[i] = upperCaseChar(cs[i]);
        }
        return String.valueOf(cs);
    }

    public final static String lowerCaseString(String str) {
        char[] cs = str.toCharArray();
        for (int i = 0; i < cs.length; i++) {
            cs[i] = lowerCaseChar(cs[i]);
        }
        return String.valueOf(cs);
    }

    public final static String upperCaseFirst(String str) {
        char[] cs = str.toCharArray();
        cs[0] = upperCaseChar(cs[0]);
        return String.valueOf(cs);
    }

    public final static String lowerCaseFirst(String str) {
        char[] cs = str.toCharArray();
        cs[0] = lowerCaseChar(cs[0]);
        return String.valueOf(cs);
    }

    public final static char upperCaseChar(char c) {
        if (c > 96 && c < 123) {
            c -= 32;
        }
        return c;
    }

    public final static char lowerCaseChar(char c) {
        if (c > 64 && c < 91) {
            c += 32;
        }
        return c;
    }

    public final static boolean isPhoneOrMobile(String phone) {
        return isMobile(phone) || isPhone(phone);
    }

    private final static String EMAIL_REGEX = "^[\\w-_\\.+]*[\\w-_\\.]\\@([\\w]+\\.)+[\\w]+[\\w]$";

    public final static boolean isEmail(String email) {
        return email.matches(EMAIL_REGEX);
    }

    private final static String MOBILE_REGEX = "^[1][3,4,5,7,8][0-9]{9}$";

    /**
     * 手机号验证
     * 
     * @author ：shijing 2016年12月5日下午4:34:46
     * @param str
     * @return 验证通过返回true
     */
    public static boolean isMobile(final String mobile) {
        return mobile.matches(MOBILE_REGEX);
    }

    private final static String PHONE_REGEX_1 = "^[1][3,4,5,7,8][0-9]{9}$";
    private final static String PHONE_REGEX_2 = "^[1-9]{1}[0-9]{5,8}$";

    /**
     * 电话号码验证
     * 
     * @author ：shijing 2016年12月5日下午4:34:21
     * @param str
     * @return 验证通过返回true
     */
    public static boolean isPhone(final String phone) {
        if (phone.length() > 9) {
            return phone.matches(PHONE_REGEX_1);
        } else {
            return phone.matches(PHONE_REGEX_2);
        }
    }

    private final static String CAR_NUM = "^[\u4e00-\u9fa5]{1}[A-Z]{1}[A-Z_0-9]{5}$";

    public static boolean isCarNum(String car) {
        return car.matches(CAR_NUM);
    }

    /**
     * 匹配Luhn算法：可用于检测银行卡卡号
     * 
     * @param cardNo
     * @return
     */
    public static boolean isBankCard(String cardNo) {
        int[] cardNoArr = new int[cardNo.length()];
        for (int i = 0; i < cardNo.length(); i++) {
            cardNoArr[i] = Integer.parseInt(String.valueOf(cardNo.charAt(i)));
        }
        for (int i = cardNoArr.length - 2; i >= 0; i -= 2) {
            cardNoArr[i] <<= 1;
            cardNoArr[i] = cardNoArr[i] / 10 + cardNoArr[i] % 10;
        }
        int sum = 0;
        for (int i = 0; i < cardNoArr.length; i++) {
            sum += cardNoArr[i];
        }
        return sum % 10 == 0;
    }

    public static String replaceMid(String start, String end, String source, String target) {
        char[] startChars = start.toCharArray();
        char[] endChars = end.toCharArray();

        StringBuilder all = new StringBuilder();
        StringBuilder mid = new StringBuilder();

        char[] sourceChars = source.toCharArray();
        boolean flag = true;
        for (int i = 0; i < sourceChars.length; i++) {
            char temp = sourceChars[i];
            if (flag) {
                if (temp == startChars[0]) {
                    boolean tf = true;
                    int j = 0;
                    for (; j < startChars.length; j++) {
                        if (sourceChars[i + j] != startChars[j]) {
                            tf = false;
                            break;
                        }
                    }
                    if (tf) {
                        flag = false;
                        i = i + j;
                        int k = i + 1;
                        if (k < sourceChars.length && sourceChars[k] == '\r') {
                            i = k;
                        }
                        k = i + 1;
                        if (k < sourceChars.length && sourceChars[k] == '\n') {
                            i = k;
                        }
                    } else {
                        all.append(temp);
                    }
                } else {
                    all.append(temp);
                }
            } else {
                if (temp == endChars[0]) {
                    boolean tf = true;
                    int j = 0;
                    for (; j < endChars.length; j++) {
                        if (sourceChars[i + j] != endChars[j]) {
                            tf = false;
                            break;
                        }
                    }
                    if (tf) {
                        flag = true;
                        i = i + j - 1;
                        int k = i + 1;
                        if (k < sourceChars.length && sourceChars[k] == '\r') {
                            i = k;
                        }
                        k = i + 1;
                        if (k < sourceChars.length && sourceChars[k] == '\n') {
                            i = k;
                        }
                        if (target == null) {
                            String mids = mid.toString();
                            all.append(mids);
                        } else {
                            all.append(target);
                        }
                        mid.setLength(0);
                    } else {
                        mid.append(temp);
                    }
                } else {
                    mid.append(temp);
                }
            }
        }

        return all.toString();
    }

    public static String findString(String from, String find) {
        Pattern pattern = Pattern.compile(find);
        Matcher matcher = pattern.matcher(from);
        if (matcher.find()) {
            return matcher.group(0);
        }
        return null;
    }

    public static String findStringG1(String from, String find) {
        Pattern pattern = Pattern.compile(find);
        Matcher matcher = pattern.matcher(from);
        if (matcher.find()) {
            return matcher.group(1);
        }
        return null;
    }

    public static String[] split(String str, String regex) {
        return str.split(regex);
    }
    
    public static String removeSuffix(String name) {
    	if (name.contains(".")) {
    		name = name.split("\\.")[0];
        }
    	return name;
    }
}
